#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   APP_WriteDataByIdentifier_0x2E_test.py
@Time    :   2025/04/10 13:31:28
@Author  :   YangLiang 
@Version :   1.0
@Contact :   yangl@genvict.com
@License :   (C)Copyright 2022-2025
@Desc    :   None
'''

import pytest
import logging
import time
import allure
import sys
from pytest_assume.plugin import assume
import Set_up

sys.dont_write_bytecode = True

# 支持的DID列表 (DID, 数据长度, 描述)
supported_dids = [
    ("F0 FA", Set_up.SoftwareIdentificationCode_hex),                           # 整车厂定义零件号
    ("F1 90", Set_up.VINDataIdentifier_hex),                                    # 车辆识别号
    ("F1 A9", Set_up.ElectricalControlUnitConfigurationFileNumber_hex),         # 电控单元配置文件号
    # ("F1 8C", Set_up.ExactTraceCode_hex),                          # 车辆识别号
    ("78 02", Set_up.OBU_ID_hex),
    ("78 03", Set_up.OBU_SN_hex),
    ("78 04", Set_up.OBU_BluetoothName_hex),
]

WriteDataByIdentifier_NRC13 = [
    ("2E", "缺少DID"),
    ("2E F1", "DID少字节"),
    ("2E F1 84", "少数据"),
    ("2E F1 90" + "00" * 16, "少一个数据字节"),
    ("2E F1 90" + "00" * 18, "多一个数据字节"),
    ("2E F1 A9" + "00" * 4, "少一个数据字节"),
    ("2E F1 A9" + "00" * 6, "多一个数据字节"),
]

# 不支持的DID列表
WriteDataByIdentifier_NRC31 = [
    ("F0 90 01", "备份软件版本号"),
    ("F0 32 02", "标定版本号"),
    ("F0 A0 03", "备区Bootloader版本号"),
    ("F0 31 04", "标定零件号"),
    ("F0 F0 05 06", "当前运行分区信息"),
    ("F0 F4 07", "子部件当前运行分区信息"),
    ("F0 F2 02", "获取安装进度和结果"),
    ("FD 32 01", "华为电子标签"),
    ("F1 5C 02", "密钥灌装状态"),
    ("F0 38 03", "无效"),
    ("F0 39 04 05", "无效"),
    ("F0 40 06", "无效"),
    ("F0 36 01", "无效"),
    ("F1 84 25 0F 20", "指纹"),
]

# 测试用例类
class Test_APP_WriteDataByIdentifier_Phy(object):

    @allure.severity('normal')
    @allure.title('物理寻址-扩展会话-写入DID正响应')
    @allure.description('测试物理寻址扩展会话下写入DID的正响应')
    @pytest.mark.parametrize("did, resp", supported_dids, ids=[f"Request {did[0]}" for did in supported_dids])
    def test_WriteDataByIdentifier_Extended_phy(self, action, Driver, did, resp):
        """测试读取支持的DID"""
        iStep = 1
        WriteData = resp
        # 发送2E服务请求,写入DID
        req = f"2E {did}" + WriteData
        resp = f"6E {did}"
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, resp, 3, iStep, True)
        # 发送22服务请求,写读取DID, 校验写入的数据
        req = f"22 {did}"
        resp = f"62 {did}" + WriteData
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, resp, 0, iStep, False)
        # 重启后读取写入信息是否正确
        iStep = Driver['CAN'].restartETC_Power(Driver, iStep)
        req = f"22 {did}"
        resp = f"62 {did}" + WriteData
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, resp, 3, iStep, False)  

    @allure.severity('normal')
    @allure.title('物理寻址-扩展会话-写入DID负响应NRC13')
    @allure.description('测试物理寻址扩展会话下读取长度不对的DID应返回NRC13')
    @pytest.mark.parametrize("req,desc", WriteDataByIdentifier_NRC13, ids=[f"Request {req}" for req,desc in WriteDataByIdentifier_NRC13])
    def test_WriteDataByIdentifier_NRC13_Extended_phy(self, action, Driver, req, desc):
        iStep = 1
        # 发送22服务请求
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, "7F 2E 13", 3, iStep, True)
        

    @allure.severity('normal')
    @allure.title('物理寻址-扩展会话-写入DID负响应NRC31')
    @allure.description('测试物理寻址扩展会话下写入不支持的DID应返回NRC31')
    @pytest.mark.parametrize("did,desc", WriteDataByIdentifier_NRC31, ids=[f"Request {did}" for did,desc in WriteDataByIdentifier_NRC31])
    def test_WriteDataByIdentifier_NRC31_Extended_phy(self, action, Driver, did, desc):
        """测试读取不支持的DID应返回NRC31"""
        iStep = 1
        # 发送22服务请求
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, f"2E {did} ", "7F 2E 31", 3, iStep, True)


    @allure.severity('normal')
    @allure.title('物理寻址-扩展会话-未安全解锁写入DID负响应NRC33')
    @allure.description('测试物理寻址扩展会话下未安全解锁写入DID应返回NRC33')
    @pytest.mark.parametrize("did,resp", supported_dids, ids=[f"Request {did}" for did,resp in supported_dids])
    def test_WriteDataByIdentifier_NRC33_Extended_phy(self, action, Driver, did, resp):
        """测试未安全解锁写入DID应返回NRC33"""
        iStep = 1
        # 发送22服务请求
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, f"2E {did}", "7F 2E 33", 3, iStep, False)
   

    @allure.severity('normal')
    @allure.title('物理寻址-扩展会话-车速高于3kph写入DID负响应NRC22')
    @allure.description('测试物理寻址扩展会话下车速高于3kph写入DID负响应NRC22')
    @pytest.mark.parametrize("did,resp", supported_dids, ids=[f"Request {did}" for did,resp in supported_dids])
    def test_WriteDataByIdentifier_NRC22_Extended_phy(self, action, Driver, did, resp):
        """测试车速限制下的DID读取"""
        iStep = 1
        # 设置车速大于3kph
        iStep = Driver['CAN'].SetVehicleSpeed(Driver, iStep, 8)
        # 尝试写入DID应返回NRC22
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver,f"2E {did} {resp}", "7F 2E 22", 3, iStep, True)
        # 重置车速
        iStep = Driver['CAN'].SetVehicleSpeed(Driver, iStep, 0)


    '''NRC priority '''
    @allure.severity('minor')
    @allure.title('物理寻址扩展会话下NRC13 NRC31优先级测试')
    @allure.description('测试物理寻址扩展会话下NRC13 NRC31优先级测试')
    def test_WriteDataByIdentifier_NRC13andNRC31_Priority_Extended_Phy(self, action, Driver):
        iStep = 1
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E FF F0', '7F 2E 13', 3, iStep, True)

    @allure.severity('minor')
    @allure.title('物理寻址扩展会话下NRC13 NRC22优先级测试')
    @allure.description('测试物理寻址扩展会话下NRC13 NRC22优先级测试')
    def test_WriteDataByIdentifier_NRC13andNRC22_Priority_Extended_Phy(self, action, Driver):
        iStep = 1
        # 设置车速大于3kph
        iStep = Driver['CAN'].SetVehicleSpeed(Driver, iStep, 8)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E FF F0', '7F 2E 13', 3, iStep, True)
        # 重置车速
        iStep = Driver['CAN'].SetVehicleSpeed(Driver, iStep, 0)

    @allure.severity('minor')
    @allure.title('物理寻址扩展会话下NRC31 NRC22优先级测试')
    @allure.description('测试物理寻址扩展会话下NRC31 NRC22优先级测试')
    def test_WriteDataByIdentifier_NRC31andNRC22_Priority_Extended_Phy(self, action, Driver):
        iStep = 1
        # 设置车速大于3kph
        iStep = Driver['CAN'].SetVehicleSpeed(Driver, iStep, 8)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 00 25 0F 20', '7F 2E 31', 3, iStep, True)
        # 重置车速
        iStep = Driver['CAN'].SetVehicleSpeed(Driver, iStep, 0)

    @allure.severity('normal')
    @allure.title('物理寻址-扩展会话-未安全解锁写入长度错误的DID响应NR33')
    @allure.description('测试物理寻址扩展会话下未安全解锁写入长度错误的DID响应NR33')
    def test_WriteDataByIdentifier_NRC33andNRC13_Priority_Extended_phy(self, action, Driver):
        """测试读取支持的DID 诊断调查表里33优先级高于13"""
        iStep = 1
        # 发送2E服务请求,写入DID
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 90', '7F 2E 33', 2, iStep, False)

    @allure.severity('normal')
    @allure.title('物理寻址-扩展会话-未安全解锁写入错误的DID响应NR33')
    @allure.description('测试物理寻址扩展会话下未安全解锁写入错误的DID响应NR33')
    def test_WriteDataByIdentifier_NRC33andNRC31_Priority_Extended_phy(self, action, Driver):
        """测试读取支持的DID 诊断调查表33优先级高于31"""
        iStep = 1
        # 发送2E服务请求,写入DID
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 84 01 00', '7F 2E 33', 2, iStep, False)    



class Test_APP_WriteDataByIdentifier_Func(object):
    @allure.severity('normal')
    @allure.title('功能寻址默认会话-写入DID正响应')
    @allure.description('测试功能寻址默认会话下写入DID的正响应')
    @pytest.mark.parametrize("did, resp", supported_dids, ids=[f"Request {did[0]}" for did in supported_dids])
    def test_WriteDataByIdentifier_Extended_Func(self, action, Driver, did, resp):
        """测试读取支持的DID"""
        iStep = 1
        # 发送2E服务请求,写入DID
        req = f"2E {did}" + resp
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, "", 3, iStep, True, "UDSFun")

    @allure.severity('normal')
    @allure.title('功能寻址-扩展会话-写入DID负响应NRC13')
    @allure.description('测试功能寻址扩展会话下读取长度不对的DID应返回NRC13')
    @pytest.mark.parametrize("req,desc", WriteDataByIdentifier_NRC13, ids=[f"Request {req}" for req,desc in WriteDataByIdentifier_NRC13])
    def test_WriteDataByIdentifier_NRC13_Extended_Func(self, action, Driver, req, desc):
        iStep = 1
        # 发送22服务请求 不支持功能寻址，NRC13也不回应
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, "", 3, iStep, True, "UDSFun")
        

    @allure.severity('normal')
    @allure.title('功能寻址-扩展会话-写入DID负响应NRC31')
    @allure.description('测试功能寻址扩展会话下写入不支持的DID应返回NRC31')
    @pytest.mark.parametrize("did,desc", WriteDataByIdentifier_NRC31, ids=[f"Request {did}" for did,desc in WriteDataByIdentifier_NRC31])
    def test_WriteDataByIdentifier_NRC31_Extended_Func(self, action, Driver, did, desc):
        """测试读取不支持的DID应返回NRC31"""
        iStep = 1
        # 发送22服务请求
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, f"2E {did}", "", 3, iStep, True, "UDSFun")
    